#include <utility>
#include "ZDataBase.h"
#include "ZDataFrame.h"
#include "ZColView.h"
#include "ZDataView.h"


#ifndef ZDATAFRAME_CPP
#define ZDATAFRAME_CPP



template<typename StringType>
NDFrame::ZDataFrame<StringType> &NDFrame::ZDataFrame<StringType>::operator=(const ZDataFrame &other) {
    if (this == &other) {
        return *this;
    }

    deallocate();

    this->m_size = other.m_size;
    this->m_capacity = other.m_capacity;
    allocate(this->m_capacity);
    for (size_t i = 0; i < other.m_size; ++i) {
        this->ItemPtr.get()[i] = other.ItemPtr.get()[i];
    }

    return *this;
}


template<typename StringType>
NDFrame::ZDataFrame<StringType> &NDFrame::ZDataFrame<StringType>::operator=(ZDataFrame &&other) noexcept {
    if (this == &other) {
        return *this;
    }

    deallocate();
    this->m_size = other.m_size;
    this->m_capacity = other.m_capacity;
    this->ItemPtr = std::move(other.ItemPtr);

    other.m_size = 0;
    other.m_capacity = 0;
    other.ItemPtr = nullptr;

    return *this;
}



template<typename StringType>
void NDFrame::ZDataFrame<StringType>::reserve(size_t new_capacity) {
    std::shared_ptr<ItemType[]> new_ptr = std::shared_ptr<ItemType[]>(new ItemType[new_capacity],
                                                                      std::default_delete<ItemType[]>());
    std::copy(this->ItemPtr.get(), this->ItemPtr.get() + this->m_size, new_ptr.get());
    this->ItemPtr = new_ptr;
    this->m_capacity = new_capacity;
}




//////////////////////////////////////////////////////////////////////////////
//							获取对应字段值
//////////////////////////////////////////////////////////////////////////////

template<typename StringType>
void NDFrame::ZDataFrame<StringType>::sort_values(const Field field_, bool descending) {
    if (this->empty()) {
        throw std::runtime_error("DataFrame is empty");
    }

    std::function<bool(const ItemType &, const ItemType &)> compare;

    switch (field_) {
        case Field::IDX:
            compare = [](const ItemType &a, const ItemType &b) { return a.idx < b.idx; };
            break;
        case Field::X0:
            compare = [](const ItemType &a, const ItemType &b) { return a.x0 < b.x0; };
            break;
        case Field::Y0:
            compare = [](const ItemType &a, const ItemType &b) { return a.y0 < b.y0; };
            break;
        case Field::X1:
            compare = [](const ItemType &a, const ItemType &b) { return a.x1 < b.x1; };
            break;
        case Field::Y1:
            compare = [](const ItemType &a, const ItemType &b) { return a.y1 < b.y1; };
            break;
        case Field::WIDTH:
            compare = [](const ItemType &a, const ItemType &b) { return a.width < b.width; };
            break;
        case Field::HEIGHT:
            compare = [](const ItemType &a, const ItemType &b) { return a.height < b.height; };
            break;
        default:
            throw std::invalid_argument("Invalid field name for sorting");
    }

    if (descending) {
        std::sort(this->ItemPtr.get(), this->ItemPtr.get() + this->m_size,
                  [compare](const ItemType &a, const ItemType &b) {
                      return compare(b, a);
                  });
    } else {
        std::sort(this->ItemPtr.get(), this->ItemPtr.get() + this->m_size, compare);
    }
}


//////////////////////////////////////////////////////////////////////////////
////					  对应字段值： 对df.txt 进行行合并
//////////////////////////////////////////////////////////////////////////////
template<typename StringType>
NDFrame::ZDataFrame<StringType>
NDFrame::ZDataFrame<StringType>::DF_merge_line(int width, int height, StringType &&sep) {
    if (this->m_size < 2) {
        return *this;
    }

    ZDataFrame mergedFrame(*this);

    size_t i = 0;
    while (i < mergedFrame.m_size - 1) {
        ItemType &current = mergedFrame.ItemPtr.get()[i];
        ItemType &next = mergedFrame.ItemPtr.get()[i + 1];

        if (std::abs(next.x0 - current.x1) < width && std::abs(next.y0 - current.y0) < height) {
            current.text += sep + next.text;
            current.x0 = std::min(current.x0, next.x0);
            current.y0 = std::min(current.y0, next.y0);
            current.x1 = std::max(current.x1, next.x1);
            current.y1 = std::max(current.y1, next.y1);
            current.width = current.x1 - current.x0;
            current.height = std::max(current.height, next.height);

            for (size_t j = i + 1; j < mergedFrame.m_size - 1; ++j) {
                mergedFrame.ItemPtr.get()[j] = mergedFrame.ItemPtr.get()[j + 1];
            }
            --mergedFrame.m_size;
        } else {
            ++i;
        }
    }
    return mergedFrame;
}


template<typename StringType>
void NDFrame::ZDataFrame<StringType>::reset_index() {
    if (this->empty()) {
        return;
    }
    for (size_t i = 0; i < this->m_size; ++i) {
        this->ItemPtr.get()[i].idx = static_cast<int>(i);
    }
}


template<typename StringType>
NDFrame::ZDataFrame<StringType>
NDFrame::ZDataFrame<StringType>::DF_indices_to_df(const std::vector<size_t> &indices) const {
    if (indices.empty()) {
        throw std::out_of_range("indices is empty");
    }

    std::unordered_set<size_t> indices_set(indices.begin(), indices.end());
    ZDataFrame newFrame(indices.size());

    size_t j = 0;
    for (size_t i = 0; i < this->m_size; ++i) {
        if (indices_set.find(this->ItemPtr.get()[i].idx) != indices_set.end()) {
            newFrame.ItemPtr.get()[j] = this->ItemPtr.get()[i];
            newFrame.ItemPtr.get()[j].idx = static_cast<int>(j);
            j++;
        }
    }

    newFrame.m_size = j;
    return newFrame;
}


template<typename StringType>
NDFrame::ZDataFrame<StringType> NDFrame::ZDataFrame<StringType>::DF_pointers_to_df(const VecItemPtr &pointers) const {
    if (pointers.empty()) {
        throw std::out_of_range("pointers is empty");
    }

    std::unordered_set<ItemType *> pointers_set(pointers.begin(), pointers.end());
    ZDataFrame newFrame(pointers.size());

    size_t j = 0;
    for (size_t i = 0; i < this->m_size; ++i) {
        if (pointers_set.find(&this->ItemPtr.get()[i]) != pointers_set.end()) {
            newFrame.ItemPtr.get()[j] = this->ItemPtr.get()[i];
            newFrame.ItemPtr.get()[j].idx = static_cast<int>(j); /* 更新新DataFrame中的索引 */
            j++;
        }
    }

    newFrame.m_size = j;
    return newFrame;
}


//////////////////////////////////////////////////////////////////////////////
////					  删除函数
//////////////////////////////////////////////////////////////////////////////
template<typename StringType>
NDFrame::ZDataFrame<StringType>
NDFrame::ZDataFrame<StringType>::DF_drop_indice(const std::vector<size_t> &indices) const {
    if (indices.empty()) {
        return ZDataFrame(0);
    }
    std::unordered_set<size_t> to_drop(indices.begin(), indices.end());

    size_t new_size = this->m_size;
    for (size_t i = 0; i < this->m_size; ++i) {
        if (to_drop.find(this->ItemPtr.get()[i].idx) != to_drop.end()) {
            new_size--;
        }
    }

    ZDataFrame newFrame(new_size);

    size_t j = 0;
    for (size_t i = 0; i < this->m_size; ++i) {
        if (to_drop.find(this->ItemPtr.get()[i].idx) == to_drop.end()) {
            newFrame.ItemPtr.get()[j++] = this->ItemPtr.get()[i];
        }
    }
    newFrame.m_size = new_size;
    return newFrame;
}


template<typename StringType>
NDFrame::ZDataFrame<StringType> NDFrame::ZDataFrame<StringType>::DF_drop_pointer(const VecItemPtr &pointers) const {
    std::unordered_set<ItemType *> to_drop(pointers.begin(), pointers.end());

    size_t new_size = this->m_size - to_drop.size();
    ZDataFrame newFrame(new_size);

    size_t j = 0;
    for (size_t i = 0; i < this->m_size; ++i) {
        if (to_drop.find(&this->ItemPtr.get()[i]) == to_drop.end()) {
            newFrame.ItemPtr.get()[j++] = this->ItemPtr.get()[i];
        }
    }
    newFrame.m_size = new_size;
    return newFrame;
}


template<typename StringType>
void NDFrame::ZDataFrame<StringType>::drop_indice(const std::vector<size_t> &indices, bool inplace) {
    if (indices.empty()) {
        return;
    }
    if (inplace) {
        drop_indice_inplace(indices);
    } else {
        *this = drop_indice_copy(indices);
    }
}


template<typename StringType>
void NDFrame::ZDataFrame<StringType>::drop_indice_inplace(const std::vector<size_t> &indices) {
    std::vector<size_t> sorted_indices = indices;
    std::sort(sorted_indices.begin(), sorted_indices.end());

    size_t new_size = this->m_size - sorted_indices.size();
    size_t current_index = 0;

    for (size_t i = 0; i < this->m_size; ++i) {
        if (current_index < sorted_indices.size() && i == sorted_indices[current_index]) {
            ++current_index;
        } else {
            this->ItemPtr[i - current_index] = this->ItemPtr[i];
        }
    }

    this->m_size = new_size;
}


template<typename StringType>
NDFrame::ZDataFrame<StringType>
NDFrame::ZDataFrame<StringType>::drop_indice_copy(const std::vector<size_t> &indices) const {
    std::vector<size_t> sorted_indices = indices;
    std::sort(sorted_indices.begin(), sorted_indices.end());

    ZDataFrame new_frame(this->m_capacity);
    new_frame.m_size = this->m_size - sorted_indices.size();

    size_t current_index = 0;
    for (size_t i = 0; i < this->m_size; ++i) {
        if (current_index < sorted_indices.size() && i == sorted_indices[current_index]) {
            ++current_index;
        } else {
            new_frame.ItemPtr[i - current_index] = this->ItemPtr[i];
        }
    }

    return new_frame;
}


template<typename StringType>
void NDFrame::ZDataFrame<StringType>::drop_pointer(const VecItemPtr &pointers) {
    std::unordered_set<ItemType *> to_drop(pointers.begin(), pointers.end());

    size_t j = 0;
    for (size_t i = 0; i < this->m_size; ++i) {
        if (to_drop.find(&this->ItemPtr.get()[i]) == to_drop.end()) {
            if (i != j) {
                this->ItemPtr.get()[j] = std::move(this->ItemPtr.get()[i]);
            }
            j++;
        }
    }
    this->m_size = j;
}


template<typename StringType>
void NDFrame::ZDataFrame<StringType>::drop_duplicates(const Field field_) {
    if (this->m_size < 2) {
        return;
    }

    std::unordered_set<int> seen;
    size_t new_size = 0;

    std::function<int(const ItemType &)> getField;

    switch (field_) {
        case Field::IDX:
            getField = [](const ItemType &item) { return item.idx; };
            break;
        case Field::X0:
            getField = [](const ItemType &item) { return item.x0; };
            break;
        case Field::Y0:
            getField = [](const ItemType &item) { return item.y0; };
            break;
        case Field::X1:
            getField = [](const ItemType &item) { return item.x1; };
            break;
        case Field::Y1:
            getField = [](const ItemType &item) { return item.y1; };
            break;
        case Field::WIDTH:
            getField = [](const ItemType &item) { return item.width; };
            break;
        case Field::HEIGHT:
            getField = [](const ItemType &item) { return item.height; };
            break;
        default:
            throw std::invalid_argument("Invalid field name for drop_duplicates");
    }

    for (size_t i = 0; i < this->m_size; ++i) {
        int key = getField(this->ItemPtr.get()[i]);

        if (seen.find(key) == seen.end()) {
            seen.insert(key);
            this->ItemPtr.get()[new_size++] = this->ItemPtr.get()[i];
        }
    }

    this->m_size = new_size;
}


//////////////////////////////////////////////////////////////////////////////
////                  对应字段值： 对df.txt df.txt_sep是否在容器内
//////////////////////////////////////////////////////////////////////////////

template<typename StringType>
bool NDFrame::ZDataFrame<StringType>::isin(const std::vector<StringType> &field, ZDataFrame &dataframe) const {
    std::vector<size_t> indices;
    bool result = isin(field, indices);
    if (result) {
        dataframe = DF_indices_to_df(indices);
    }
    return result;
}


//////////////////////////////////////////////////////////////////////////////
////					对应字段值： 对df.txt df.txt_sep进行字符拼接
//////////////////////////////////////////////////////////////////////////////
template<typename StringType>
StringType NDFrame::ZDataFrame<StringType>::join(Field field_, const StringType &Char_) const {
    if (this->empty() || Char_.size() >= 2) {
        return {};
    }

    std::function<const StringType &(const ItemType &)> getField;
    if (field_ == Field::TEXT) {
        getField = [](const ItemType &item) -> const StringType & { return item.text; };
    } else if (field_ == Field::TEXT_SEP) {
        getField = [](const ItemType &item) -> const StringType & { return item.text_sep; };
    }

    std::basic_ostringstream<CharType> oss;
    for (size_t i = 0; i < this->m_size; ++i) {
        if (i != 0 && !Char_.empty()) {
            oss << Char_;
        }
        oss << getField(this->ItemPtr.get()[i]);
    }
    return oss.str();
}



template<typename StringType>
StringType NDFrame::ZDataFrame<StringType>::join_replace(Field field_, CharType oldChar, CharType newChar,
                                                         const StringType &Char_) const {
    if (this->empty() || Char_.size() >= 2) {
        return {};
    }
    std::function<const StringType &(const ItemType &)> getField;
    if (field_ == Field::TEXT) {
        getField = [](const ItemType &item) -> const StringType & { return item.text; };
    } else if (field_ == Field::TEXT_SEP) {
        getField = [](const ItemType &item) -> const StringType & { return item.text_sep; };
    }
    std::basic_ostringstream<CharType> oss;
    for (size_t i = 0; i < this->m_size; ++i) {
        if (i != 0 && !Char_.empty()) {
            oss << Char_;
        }
        for (auto c: getField(this->ItemPtr.get()[i])) {
            if (c == oldChar) {
                oss << newChar;
            } else {
                oss << c;
            }
        }
    }
    return oss.str();
}


template<typename StringType>
StringType NDFrame::ZDataFrame<StringType>::join_replace2(Field field_,
                                                          CharType oldChar0,
                                                          CharType newChar0,
                                                          CharType oldChar1,
                                                          CharType newChar1,
                                                          const StringType &Char_) const {
    if (this->empty()) {
        return {};
    }
    if (Char_.size() >= 2) {
        return {};
    }
    std::function<const StringType &(const ItemType &)> getField;
    if (field_ == Field::TEXT) {
        getField = [](const ItemType &item) -> const StringType & { return item.text; };
    } else if (field_ == Field::TEXT_SEP) {
        getField = [](const ItemType &item) -> const StringType & { return item.text_sep; };
    }
    std::basic_ostringstream<CharType> oss;
    for (size_t i = 0; i < this->m_size; ++i) {
        if (i != 0 && !Char_.empty()) {
            oss << Char_;
        }
        for (auto c: getField(this->ItemPtr.get()[i])) {
            if (c == oldChar0) {
                oss << newChar0;
            } else if (c == oldChar1) {
                oss << newChar1;
            } else {
                oss << c;
            }
        }
    }
    return oss.str();
}


//////////////////////////////////////////////////////////////////////////////
////							对应字段值： 对df.txt df.txt_sep进行字符替换
//////////////////////////////////////////////////////////////////////////////
template<typename StringType>
void NDFrame::ZDataFrame<StringType>::replace(Field txt, CharType oldChar, CharType newChar) {
    if (this->m_size == 0) {
        return;
    }

    /*根据 txt 选择合适的成员变量 */
    auto get_text_member = [&](size_t i) -> StringType & {
        switch (txt) {
            case Field::TEXT:
                return this->ItemPtr.get()[i].text;
            case Field::TEXT_SEP:
                return this->ItemPtr.get()[i].text_sep;
            default:
                throw std::invalid_argument("Invalid field name for replace(must is:TEXT,TEXT_SEP)");
        }
    };

    for (size_t i = 0; i < this->m_size; ++i) {
        StringType &modified_text = get_text_member(i);
        std::replace(modified_text.begin(), modified_text.end(), oldChar, newChar);
    }
}


template<typename StringType>
void NDFrame::ZDataFrame<StringType>::replace(Field txt,
                                              CharType oldChar0,
                                              CharType newChar0,
                                              CharType oldChar1,
                                              CharType newChar1) {
    if (this->m_size == 0) {
        return;
    }

    /* 根据 txt 选择合适的成员变量 */
    auto get_text_member = [&](size_t i) -> StringType & {
        switch (txt) {
            case Field::TEXT:
                return this->ItemPtr.get()[i].text;
            case Field::TEXT_SEP:
                return this->ItemPtr.get()[i].text_sep;
            default:
                throw std::invalid_argument("Invalid field name for replace(must is:TEXT,TEXT_SEP)");
        }
    };

    for (size_t i = 0; i < this->m_size; ++i) {
        StringType &modified_text = get_text_member(i);
        for (auto &j: modified_text) {
            if (j == oldChar0) {
                j = newChar0;
            } else if (j == oldChar1) {
                j = newChar1;
            }
        }
    }
}


template<typename StringType>
template<typename MapType>
void NDFrame::ZDataFrame<StringType>::multi_replace_df_text_impl(Field txt, const MapType &replacements) {
    if (this->m_size == 0) {
        return;
    }

    /* 根据 txt 选择合适的成员变量 */
    auto get_text_member = [&](size_t i) -> StringType & {
        switch (txt) {
            case Field::TEXT:
                return this->ItemPtr.get()[i].text;
            case Field::TEXT_SEP:
                return this->ItemPtr.get()[i].text_sep;
            default:
                throw std::invalid_argument("Invalid field name for multi_replace(must is:TEXT,TEXT_SEP)");
        }
    };

    for (size_t i = 0; i < this->m_size; ++i) {
        StringType &modified_text = get_text_member(i);
        for (const auto &replacement: replacements) {
            const StringType &from = replacement.first;
            const StringType &to = replacement.second;
            size_t pos = 0;
            while ((pos = modified_text.find(from, pos)) != StringType::npos) {
                modified_text.replace(pos, from.length(), to);
                pos += to.length();
            }
        }
    }
}


template<typename StringType>
void NDFrame::ZDataFrame<StringType>::multi_replace(Field txt,
                                                    const std::map<StringType, StringType> &replacements) {
    multi_replace_df_text_impl(txt, replacements);
}


template<typename StringType>
void NDFrame::ZDataFrame<StringType>::multi_replace(Field txt,
                                                    const std::unordered_map<StringType, StringType> &replacements) {
    multi_replace_df_text_impl(txt, replacements);
}


//////////////////////////////////////////////////////////////////////////////
////				   通用函数 对应字段值进行过滤
//////////////////////////////////////////////////////////////////////////////
template<typename StringType>
bool NDFrame::ZDataFrame<StringType>::filter(const std::function<bool(const ItemType &)> &predicate,
                                             std::vector<NDFrame::DataItem<StringType> *> &out_pointers) const {
    if (!out_pointers.empty()) { out_pointers.clear(); }
    out_pointers.reserve((int) (static_cast<double>(this->size()) * 0.5) + 2);
    for (size_t i = 0; i < this->m_size; ++i) {
        if (predicate(this->ItemPtr.get()[i])) {
            out_pointers.push_back(&this->ItemPtr.get()[i]);
        }
    }
    out_pointers.shrink_to_fit();
    return !out_pointers.empty();
}


template<typename StringType>
NDFrame::ZDataFrame<StringType>
NDFrame::ZDataFrame<StringType>::DF_filter(const std::function<bool(const ItemType &)> &predicate) const {
    ZDataFrame<StringType> result(this->m_size > 3 ? 3 : this->m_size);
    if (this->m_size == 0) return result;
    for (size_t i = 0; i < this->m_size; ++i) {
        if (predicate(this->ItemPtr.get()[i])) {
            result.push_back(this->ItemPtr.get()[i]);
        }
    }
    return result;

}


//////////////////////////////////////////////////////////////////////////////
////			   专用函数 对应字段值进行过滤--返回df副本（深复制）
//////////////////////////////////////////////////////////////////////////////
template<typename StringType>
NDFrame::ZDataFrame<StringType>
NDFrame::ZDataFrame<StringType>::DF_reg_impl(NDFrame::Field field, const std::vector<RegexType> &regex_) const {
    ZDataFrame<StringType> result(this->m_capacity > 3 ? 3 : this->m_capacity);
    if (this->m_size == 0) return result;

    std::function<const StringType &(const ItemType &)> getField;

    switch (field) {
        case Field::TEXT:
            getField = [](const ItemType &item) -> const StringType & { return item.text; };
            break;
        case Field::TEXT_SEP:
            getField = [](const ItemType &item) -> const StringType & { return item.text_sep; };
            break;
        default:
            throw std::invalid_argument("Invalid field");
    }

    for (size_t i = 0; i < this->m_size; ++i) {
        const StringType &field_value = getField(this->ItemPtr.get()[i]);
        for (const auto &reg: regex_) {
            if (matches_regex(field_value, reg)) {
                result.push_back(this->ItemPtr.get()[i]);
                break;
            }
        }
    }

    return result;
}



template<typename StringType>
NDFrame::ZDataFrame<StringType>
NDFrame::ZDataFrame<StringType>::DF_xyxy_impl(const std::function<bool(const DataItem<StringType> &)> &condition) const {
    ZDataFrame<StringType> result(this->m_capacity > 3 ? 3 : this->m_capacity);
    for (size_t i = 0; i < this->m_size; ++i) {
        if (condition(this->ItemPtr.get()[i])) {
            result.push_back(this->ItemPtr.get()[i]);
        }
    }
    return result;
}


template<typename StringType>
NDFrame::ZDataFrame<StringType> NDFrame::ZDataFrame<StringType>::DF_reg_common4(
        NDFrame::Field field,
        const std::vector<RegexType> &regex_, int len,
        const std::function<bool(size_t, size_t)> &compare) const {

    ZDataFrame<StringType> result(this->m_capacity > 3 ? 3 : this->m_capacity);
    if (this->m_size == 0) return result;

    std::function<const StringType &(const ItemType &)> getField;

    switch (field) {
        case Field::TEXT:
            getField = [](const ItemType &item) -> const StringType & { return item.text; };
            break;
        case Field::TEXT_SEP:
            getField = [](const ItemType &item) -> const StringType & { return item.text_sep; };
            break;
        default:
            throw std::invalid_argument("Invalid field");
    }

    for (size_t i = 0; i < this->m_size; ++i) {
        const StringType &field_value = getField(this->ItemPtr.get()[i]);
        if (compare(field_value.size(), len)) {
            for (const auto &reg: regex_) {
                if (matches_regex(field_value, reg)) {
                    result.push_back(this->ItemPtr.get()[i]);
                    break;
                }
            }
        }
    }
    return result;
}


template<typename StringType>
NDFrame::ZDataFrame<StringType> NDFrame::ZDataFrame<StringType>::DF_reg_common3(
        NDFrame::Field field,
        const std::vector<RegexType> &regex_,
        const std::function<bool(const DataItem<StringType> &)> &condition
) const {

    ZDataFrame<StringType> result(this->m_capacity > 3 ? 3 : this->m_capacity);
    if (this->m_size == 0) return result;

    std::function<const StringType &(const ItemType &)> getField;

    switch (field) {
        case Field::TEXT:
            getField = [](const ItemType &item) -> const StringType & { return item.text; };
            break;
        case Field::TEXT_SEP:
            getField = [](const ItemType &item) -> const StringType & { return item.text_sep; };
            break;
        default:
            throw std::invalid_argument("Invalid field");
    }

    for (size_t i = 0; i < this->m_size; ++i) {
        if (condition(this->ItemPtr.get()[i])) {
            const StringType &field_value = getField(this->ItemPtr.get()[i]);
            for (const auto &reg: regex_) {
                if (matches_regex(field_value, reg)) {
                    result.push_back(this->ItemPtr.get()[i]);
                    break;
                }
            }
        }
    }
    return result;
}


//////////////////////////////////////////////////////////////////////////////
////			   专用函数 对应字段值进行过滤--返回符合条件的地址集合
//////////////////////////////////////////////////////////////////////////////
template<typename StringType>
bool NDFrame::ZDataFrame<StringType>::ptr_reg_impl(VecItemPtr &out_ptr, Field field,
                                                   const std::vector<RegexType> &regex_) const {

    if (out_ptr.empty()) { out_ptr.reserve(3); }
    if (this->m_size == 0) return false;

    std::function<const StringType &(const ItemType &)> getField;

    switch (field) {
        case Field::TEXT:
            getField = [](const ItemType &item) -> const StringType & { return item.text; };
            break;
        case Field::TEXT_SEP:
            getField = [](const ItemType &item) -> const StringType & { return item.text_sep; };
            break;
        default:
            throw std::invalid_argument("Invalid field");
    }

    for (size_t i = 0; i < this->m_size; ++i) {
        for (const auto &reg: regex_) {
            if (matches_regex(getField(this->ItemPtr.get()[i]), reg)) {
                out_ptr.push_back(&this->ItemPtr.get()[i]);
                break;
            }
        }
    }
    return !out_ptr.empty();
}


template<typename StringType>
bool NDFrame::ZDataFrame<StringType>::ptr_reg_common5(
        VecItemPtr &out_ptr,
        NDFrame::Field field,
        const std::vector<RegexType> &regex_, int len,
        const std::function<bool(size_t, size_t)> &compare) const {

    if (out_ptr.empty()) { out_ptr.reserve(3); }
    if (this->m_size == 0) return false;

    std::function<const StringType &(const ItemType &)> getField;

    switch (field) {
        case Field::TEXT:
            getField = [](const ItemType &item) -> const StringType & { return item.text; };
            break;
        case Field::TEXT_SEP:
            getField = [](const ItemType &item) -> const StringType & { return item.text_sep; };
            break;
        default:
            throw std::invalid_argument("Invalid field");
    }

    for (size_t i = 0; i < this->m_size; ++i) {
        const StringType &field_value = getField(this->ItemPtr.get()[i]);
        if (compare(field_value.size(), len)) {
            for (const auto &reg: regex_) {
                if (matches_regex(field_value, reg)) {
                    out_ptr.push_back(&this->ItemPtr.get()[i]);
                    break;
                }
            }
        }
    }
    return !out_ptr.empty();
}

template<typename StringType>
bool NDFrame::ZDataFrame<StringType>::ptr_reg_common4(
        VecItemPtr &out_ptr,
        NDFrame::Field field,
        const std::vector<RegexType> &regex_,
        const std::function<bool(const ItemType &)> &condition
) const {

    if (out_ptr.empty()) { out_ptr.reserve(3); }
    if (this->m_size == 0) return false;

    std::function<const StringType &(const ItemType &)> getField;

    switch (field) {
        case Field::TEXT:
            getField = [](const ItemType &item) -> const StringType & { return item.text; };
            break;
        case Field::TEXT_SEP:
            getField = [](const ItemType &item) -> const StringType & { return item.text_sep; };
            break;
        default:
            throw std::invalid_argument("Invalid field");
    }

    for (size_t i = 0; i < this->m_size; ++i) {
        const StringType &field_value = getField(this->ItemPtr.get()[i]);
        if (condition(this->ItemPtr.get()[i])) {
            for (const auto &reg: regex_) {
                if (matches_regex(field_value, reg)) {
                    out_ptr.push_back(&this->ItemPtr.get()[i]);
                    break;
                }
            }
        }
    }
    return !out_ptr.empty();
}


template<typename StringType>
template<typename ConditionIdx>
bool NDFrame::ZDataFrame<StringType>::ptr_xyxy(VecItemPtr &out_ptr, ConditionIdx conditionIdx) const {
    if (out_ptr.empty()) { out_ptr.reserve(3); }
    if (this->m_size == 0) return false;
    for (size_t i = 0; i < this->m_size; ++i) {
        if (conditionIdx(this->ItemPtr.get()[i])) {
            out_ptr.push_back(&this->ItemPtr.get()[i]);
        }
    }
    return !out_ptr.empty();
}


//////////////////////////////////////////////////////////////////////////////
////			   使用索引进行筛选
//// DF_iloc 返回副本(深复制)
//// DV_iloc 返回视图(无复制)
//////////////////////////////////////////////////////////////////////////////
template<typename StringType>
NDFrame::ZDataFrame<StringType> NDFrame::ZDataFrame<StringType>::DF_iloc(int idx0, int idx1) const {
    if (idx0 < 0 || idx1 >= static_cast<int>(this->m_size) || idx0 > idx1) {
        throw std::out_of_range("Index range out of bounds");
    }

    ZDataFrame<StringType> result(idx1 - idx0 + 1);
    for (int i = idx0; i < idx1; ++i) {
        result.push_back(this->ItemPtr.get()[i]);
    }
    return result;
}


template<typename StringType>
bool NDFrame::ZDataFrame<StringType>::iloc(VecItemPtr &out_ptr, int idx0, int idx1) const {
    if (idx0 < 0 || idx1 >= static_cast<int>(this->m_size) || idx0 > idx1) {
        std::wcout << "Index range out of bounds\n";
        return false;
    }
    if (out_ptr.empty()) { out_ptr.reserve(7); }

    for (size_t i = 0; i < this->m_size; ++i) {
        if (this->ItemPtr.get()[i].x0 >= idx0 && this->ItemPtr.get()[i].x0 < idx1) {
            out_ptr.push_back(&this->ItemPtr.get()[i]);
        }
    }
    return !out_ptr.empty();
}


//////////////////////////////////////////////////////////////////////////////
////		   对ZDataFrame进行首次过滤返回视图
//////////////////////////////////////////////////////////////////////////////
template<typename StringType>
NDFrame::ZDataView<StringType>
NDFrame::ZDataFrame<StringType>::dv_reg_impl(Field field, const std::vector<RegexType> &regex_) const {

    if (this->m_size == 0) return ZDataView{*this, 0, 0};

    std::function<const StringType &(const ItemType &)> getField;

    switch (field) {
        case Field::TEXT:
            getField = [](const ItemType &item) -> const StringType & { return item.text; };
            break;
        case Field::TEXT_SEP:
            getField = [](const ItemType &item) -> const StringType & { return item.text_sep; };
            break;
        default:
            throw std::invalid_argument("Invalid field");
    }


    size_t startIndex = this->m_size;
    size_t endIndex = 0;

    for (size_t i = 0; i < this->m_size; ++i) {
        const StringType &field_value = getField(this->ItemPtr.get()[i]);
        bool matched = false;
        for (const auto &reg: regex_) {
            if (matches_regex(field_value, reg)) {
                matched = true;
                break;
            }
        }

        if (matched) {
            if (startIndex == this->m_size) {
                startIndex = i;
            }
            endIndex = i + 1;
        } else {
            if (startIndex != this->m_size && endIndex > 0) {
                return ZDataView{*this, startIndex, endIndex};
            }
            startIndex = this->m_size;
            endIndex = 0;
        }
    }

    if (startIndex != this->m_size && endIndex > 0) {
        return ZDataView{*this, startIndex, endIndex};
    }
    return ZDataView{*this, 0, 0};
}


template<typename StringType>
NDFrame::ZDataView<StringType> NDFrame::ZDataFrame<StringType>::dv_reg_common4(
        NDFrame::Field field,
        const std::vector<RegexType> &regex_, int len,
        const std::function<bool(size_t, size_t)> &compare) const {

    if (this->m_size == 0) return ZDataView{*this, 0, 0};;

    std::function<const StringType &(const ItemType &)> getField;

    switch (field) {
        case Field::TEXT:
            getField = [](const ItemType &item) -> const StringType & { return item.text; };
            break;
        case Field::TEXT_SEP:
            getField = [](const ItemType &item) -> const StringType & { return item.text_sep; };
            break;
        default:
            throw std::invalid_argument("Invalid field");
    }

    size_t startIndex = this->m_size;
    size_t endIndex = 0;

    for (size_t i = 0; i < this->m_size; ++i) {
        const StringType &field_value = getField(this->ItemPtr.get()[i]);
        if (compare(field_value.size(), len)) {
            for (const auto &reg: regex_) {
                if (matches_regex(field_value, reg)) {
                    if (startIndex == this->m_size) {
                        startIndex = i;
                    }
                    endIndex = i + 1;
                    break;
                }
            }
            if (startIndex != this->m_size && endIndex > 0) {
                return ZDataView{*this, startIndex, endIndex};
            }
        } else {
            if (startIndex != this->m_size && endIndex > 0) {
                return ZDataView{*this, startIndex, endIndex};
            }
            startIndex = this->m_size;
            endIndex = 0;
        }
    }

    if (startIndex != this->m_size && endIndex > 0) {
        return ZDataView{*this, startIndex, endIndex};
    }

    return ZDataView{*this, 0, 0};
}


template<typename StringType>
NDFrame::ZDataView<StringType> NDFrame::ZDataFrame<StringType>::dv_reg_common3(
        NDFrame::Field field,
        const std::vector<RegexType> &regex_,
        const std::function<bool(const ItemType &)> &condition
) const {
    if (this->m_size == 0) return ZDataView<StringType>{*this, 0, 0};

    std::function<const StringType &(const ItemType &)> getField;

    switch (field) {
        case Field::TEXT:
            getField = [](const ItemType &item) -> const StringType & { return item.text; };
            break;
        case Field::TEXT_SEP:
            getField = [](const ItemType &item) -> const StringType & { return item.text_sep; };
            break;
        default:
            throw std::invalid_argument("Invalid field");
    }

    size_t startIndex = this->m_size;
    size_t endIndex = 0;

    for (size_t i = 0; i < this->m_size; ++i) {
        if (condition(this->ItemPtr.get()[i])) {
            const StringType &field_value = getField(this->ItemPtr.get()[i]);
            for (const auto &reg: regex_) {
                if (matches_regex(field_value, reg)) {
                    if (startIndex == this->m_size) {
                        startIndex = i;
                    }
                    endIndex = i + 1;
                    break;
                }
            }
            if (startIndex != this->m_size && endIndex > 0) {
                return ZDataView<StringType>{*this, startIndex, endIndex};
            }
        } else {
            if (startIndex != this->m_size && endIndex > 0) {
                return ZDataView<StringType>{*this, startIndex, endIndex};
            }
            startIndex = this->m_size;
            endIndex = 0;
        }
    }

    if (startIndex != this->m_size && endIndex > 0) {
        return ZDataView<StringType>{*this, startIndex, endIndex};
    }

    return ZDataView<StringType>{*this, 0, 0};;
}


template<typename StringType>
template<typename ConditionInt>
NDFrame::ZDataView<StringType> NDFrame::ZDataFrame<StringType>::DV_loc(ConditionInt conditionInt) const {
    if (this->m_size == 0) return ZDataView<StringType>{*this, 0, 0};

    size_t startIndex = this->m_size;
    size_t endIndex = 0;

    for (size_t i = 0; i < this->m_size; ++i) {
        if (conditionInt(this->ItemPtr.get()[i])) {
            if (startIndex == this->m_size) {
                startIndex = i;
            }
            endIndex = i + 1;
        } else {
            if (startIndex != this->m_size && endIndex > 0) {
                return ZDataView<StringType>{*this, startIndex, endIndex};
            }
            startIndex = this->m_size;
            endIndex = 0;
        }
    }

    if (startIndex != this->m_size && endIndex > 0) {
        return ZDataView<StringType>{*this, startIndex, endIndex};
    }

    return ZDataView<StringType>{*this, 0, 0};
}

template class NDFrame::ZDataFrame<std::string>;
template class NDFrame::ZDataFrame<std::wstring>;
#endif
